// TODO

#pragma once

#include <string>
#include <vector>
#include <fstream>
#include <unordered_map>
#include <unordered_set>
#include <sstream>
#include <unordered_set>

#include "../../Utility/Log/Log.hpp"
#include "../../Utility/Static/Algorithmf.hpp"
#include "../../Utility/Data/NavObsData/GNSSObsData.hpp"

namespace ns_GNSSObsInput
{
    using namespace ns_Log;
    using namespace ns_Util;
    using namespace ns_GNSSObsData;

    class GNSSObsRecordReader
    {
    public:
        GNSSObsRecordReader()
        {
        }

    public:
        static bool ReadRecordToFile(const std::string &fileName, const std::initializer_list<GNSSType> &catchList)
        {
            std::unordered_set<GNSSType> catchs(catchList);
            std::string source = PathUtil::Src(fileName);

            std::ifstream inStream(source);
            if (!inStream.is_open())
            {
                Log(Warnning) << "Open File Failed" << '\n';
                return 0;
            }

            std::string readLineBuffer;
            // 寻找头文件终止END OF HEADER
            int lineCount = 0;
            while (true)
            {
                readLineBuffer.clear();
                std::getline(inStream, readLineBuffer);
                if (readLineBuffer.find("END OF HEADER") != std::string::npos)
                    break;

                if (lineCount>600)
                    return 0;
                
                lineCount++;
            }

            // 找到之后，开始逐历元读取
            while (inStream.rdstate() != std::ios::eofbit)
            {
                readLineBuffer.clear();
                // 第一行 ： 数据头
                std::getline(inStream, readLineBuffer);
                lineCount++;
                if(readLineBuffer.empty())
                {
                    Log(Debug)<<"读到空串了！"<<lineCount<<'\n';
                    break;
                }

                if(readLineBuffer.size()<60)
                    readLineBuffer.resize(60,' ');
                
                int year = Algorithmf::StringToInt(std::string(readLineBuffer.begin() + 2, readLineBuffer.begin() + 6));
                int month = Algorithmf::StringToInt(std::string(readLineBuffer.begin() + 7, readLineBuffer.begin() + 9));
                int day = Algorithmf::StringToInt(std::string(readLineBuffer.begin() + 10, readLineBuffer.begin() + 12));
                int hour = Algorithmf::StringToInt(std::string(readLineBuffer.begin() + 13, readLineBuffer.begin() + 15));
                int minute = Algorithmf::StringToInt(std::string(readLineBuffer.begin() + 16, readLineBuffer.begin() + 18));
                double second = Algorithmf::StringToDouble(std::string(readLineBuffer.begin() + 18, readLineBuffer.begin() + 29));
                bool mark = !Algorithmf::StringToInt(std::string(readLineBuffer.begin() + 31, readLineBuffer.begin() + 32));
                double snum = Algorithmf::StringToDouble(std::string(readLineBuffer.begin() + 32, readLineBuffer.begin() + 35));
                double clockBias = Algorithmf::StringToDouble(std::string(readLineBuffer.begin() + 41, readLineBuffer.begin() + 56));

                GNSSObsRecord::GNSSObsRecordHeader::Ptr recordHeader = std::make_shared<GNSSObsRecord::GNSSObsRecordHeader>();
                recordHeader->epoch = CommonTime(year,month,day,hour,minute,second);
                recordHeader->reciverClockBias = clockBias;
                recordHeader->useable = mark;

                std::vector<GNSSObsRecord> records(snum);
                for(int i=0;i<snum;i++)
                {
                    records[i].header = recordHeader;
                    //读取每一部分的文件
                    readLineBuffer.clear();
                    std::getline(inStream,readLineBuffer);
                    lineCount++;
                    if(readLineBuffer.size()<20)
                    {
                        records[i].header->useable = false;
                        continue;
                    }
                    
                    records[i].gnssType = GNSSTypeUtil::GetGNSSTypeByMark(readLineBuffer[0]);
                    records[i].serial = Algorithmf::StringToInt(std::string(readLineBuffer.begin()+1,readLineBuffer.begin()+3));
                    records[i].pseudoRange = Algorithmf::StringToDouble(std::string(readLineBuffer.begin()+3,readLineBuffer.begin()+17));
                    records[i].doppler = Algorithmf::StringToDouble(std::string(readLineBuffer.begin()+36,readLineBuffer.begin()+50));
                }

                Json::Value outValue;
                outValue["Size"] = snum;
                for(int i =0;i<snum;i++)
                {
                    std::string outJson;
                    records[i].Encode(&outJson);
                    outValue["Content"][i] = JsonUtil::StringToValue(outJson);
                }

                FileUtil::WriteToFile(PathUtil::ObsRecord(fileName,CommonTime(year,month,day,hour,minute,second).SecondFromRefTime()),JsonUtil::ValueToString(outValue));
            }

            inStream.close();

            return true;
        }
    };
}